package com.pds.web.device.controller;

import com.pds.common.constant.Constants;
import com.pds.common.core.controller.BaseController;
import com.pds.common.core.domain.R;
import com.pds.common.core.page.TableDataInfo;
import com.pds.common.utils.poi.ExcelUtil;
import com.pds.system.domain.FileUpload;
import com.pds.system.service.IFileUploadService;
import com.pds.utils.ExcelTemplateUtil;
import com.pds.web.device.entity.PdsTestOrganizationDevice;
import com.pds.web.device.service.PdsTestOrganizationDeviceService;
import com.pds.web.operationLog.annotation.OprLog;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.usermodel.*;
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 检测机构仪器设备表
 *
 * @author srf sunlightcs@gmail.com
 * @since 1.0.0 2024-02-19
 */
@RestController
@RequestMapping("/organizationDevice")
@Api(tags="检测机构仪器设备")
public class PdsTestOrganizationDeviceController extends BaseController {

    private static final Logger log = LoggerFactory.getLogger(PdsTestOrganizationDeviceController.class);
    @Resource
    private PdsTestOrganizationDeviceService pdsTestOrganizationDeviceService;
    @Autowired
    private IFileUploadService fileUploadService;

    /**
     * 分页查询仪器设备
     *
     *   pageNum/pageSize分页字段
     *   筛选条件字段
     * @return 查询结果
     */
    @ApiOperation("分页查询仪器设备")
    @GetMapping("/page")
    public TableDataInfo pageOrganizationDevice(PdsTestOrganizationDevice pdsTestOrganizationDevice){
        startPage();
        List<PdsTestOrganizationDevice> list = pdsTestOrganizationDeviceService.selectList(pdsTestOrganizationDevice);
        return getDataTable(list);
    }

    /**
     * 根据ID查询仪器设备
     *
     * @param id 主键
     * @return 单条数据
     */
    @ApiOperation("仪器设备详情")
    @GetMapping("/queryById/{id}")
    public R<PdsTestOrganizationDevice> queryOrganizationDeviceById(@PathVariable("id")Long id) {
        return R.ok(pdsTestOrganizationDeviceService.queryById(id));
    }

    /**
     * 创建仪器设备
     * @param pdsTestOrganizationDevice 记录
     * @return 抽查记录
     */
    @OprLog(content = "创建仪器设备")
    @ApiOperation("创建仪器设备")
    @PostMapping("/add")
    public R<PdsTestOrganizationDevice> addOrganizationDevice(@RequestBody PdsTestOrganizationDevice pdsTestOrganizationDevice){
        return R.ok(pdsTestOrganizationDeviceService.insert(pdsTestOrganizationDevice));
    }

    /**
     * 修改仪器设备
     * @param pdsTestOrganizationDevice 记录
     * @return 成功标识
     */
    @ApiOperation("修改仪器设备")
    @PostMapping("/edit")
    public R<Boolean> editOrganizationDevice(@RequestBody PdsTestOrganizationDevice pdsTestOrganizationDevice){
        return R.ok(pdsTestOrganizationDeviceService.update(pdsTestOrganizationDevice));
    }

    /**
     * 根据ID删除仪器设备
     *
     * @param id 主键
     * @return 删除是否成功
     */
    @ApiOperation("删除仪器设备")
    @DeleteMapping("/delete")
    public R<Boolean> deleteOrganizationDeviceById(@RequestParam Long id) {
        return R.ok(pdsTestOrganizationDeviceService.deleteById(id));
    }

    /**
     * 检测仪器批量导入模板下载
     */
    @GetMapping("downloadTemplate")
    public void downloadTemplate(HttpServletResponse response){
        ExcelTemplateUtil.downloadTemplate(response,"testDeviceTemplate.xlsx","仪器导入模板");
    }

    /**
     * 检测仪器批量导入
     */
    @PostMapping("importDevices")
    public R importDevices(MultipartFile file) throws Exception {
        //获取文件名+后缀
        String filename = file.getOriginalFilename();
        if (filename != null) {
            //获取其后缀
            String extension = filename.substring(filename.lastIndexOf(".") + 1);
            if (!(extension.equals("xls") || extension.equals("xlsx"))) {
                //此处为自定义异常捕获,可使用其他方式
                throw new RuntimeException("文件格式有误,请检查上传文件格式");
            }
        }
        //获取文件的输入流
        ExcelUtil excelUtil = new ExcelUtil(PdsTestOrganizationDevice.class);
        //校验表头，防止模板被改
        String topRow = excelUtil.getTopRow(file.getInputStream());
        if(!Constants.TEST_DEVICE_HEADERS.equals(topRow)){
            throw new Exception(file.getOriginalFilename()+"文件表头被更改，请用正确的模板上传!");
        }
        //读取数据
        List<PdsTestOrganizationDevice> list = excelUtil.importExcel(file.getInputStream());
        //读取并保存图片,此处未使用ExcelUtil中读取图片，是因为ExcelUtil工具类中保存图片不是用的minio，
        //如果想配置会有循环依赖等各种问题，故单独写方法处理图片
        Map map = saveImage(file.getInputStream());
        pdsTestOrganizationDeviceService.importDevices(list,map);
        return R.ok();
    }

    private Map saveImage(InputStream inputStream) throws Exception {
        XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
        XSSFSheet sheet = workbook.getSheetAt(0);
        Map<String, String> map = new HashMap<>();
        List<POIXMLDocumentPart> list = sheet.getRelations();
        for (POIXMLDocumentPart part : list) {
            if (part instanceof XSSFDrawing) {
                XSSFDrawing drawing = (XSSFDrawing) part;
                List<XSSFShape> shapes = drawing.getShapes();
                for (XSSFShape shape : shapes) {
                    XSSFPicture picture = (XSSFPicture) shape;
                    XSSFClientAnchor anchor = picture.getPreferredSize();
                    CTMarker marker = anchor.getFrom();
                    String key = marker.getRow() + "-" + marker.getCol();
                    byte[] data = picture.getPictureData().getData();
                    InputStream inputStream1 = new ByteArrayInputStream(data);
                    MultipartFile file1 = new MockMultipartFile( "仪器.png","仪器.png","application/octet-stream",inputStream1);
                    FileUpload fileUpload = fileUploadService.uploadAndReturnFileID(file1, "0");
                    map.put(key, fileUpload.getUrl());
                }
            }
        }
        IOUtils.closeQuietly(workbook);
        IOUtils.closeQuietly(inputStream);
        return map;
    }

}
